
local zhttp = require "resty.http"
local io = require("io")
local cjson = require("cjson.safe")
local string = require("string")
local math = require("math")
local config = require("config")
local limit_req = require "resty.limit.req"
local limit_count = require "resty.limit.count"
local producer = require "resty.kafka.producer"

local _M = {
    RULE_TABLE = {},
}

function _M.GET(key)
	local wafconfig = ngx.shared.wafconfig
	local retc,_ = wafconfig:get(key)
	return retc
end

function _M.SET(key,value)
	local wafconfig = ngx.shared.wafconfig
	local retc,_ = wafconfig:set(key,value)
	return retc
end

function _M.SetExt(key,value,expT)
	local wafconfig = ngx.shared.wafconfig
	local retc,_ = wafconfig:set(key,value,expT)
	return retc
end

--for timer run
function _M.syncDictToTable()
    local isSync = _M.GET("config_syncToTable")
    --nil: first load config
    if isSync ~= nil then
		local xfcfg = _M.GET("xwaf_config")
		--ngx.log(ngx.DEBUG, limitrules)
		local json = cjson.decode(xfcfg)	
		if xfcfg ~= nil and json ~= nil then
            if json.reqlimit_rule ~= cjson.null then
                --timer.lua中多个worker会执行该函数来同步变量到不同worker中
			    config.reqlimit_rule = json.reqlimit_rule	
            end
            if json.whitelist ~= cjson.null then
                config.whitelist = json.whitelist
            end
            if json.urldeny_rule ~= cjson.null then
                config.urldeny_rule = json.urldeny_rule
            end            
			ngx.log(ngx.INFO, "syncDictToTable ok,reqlimtrule")
		else
			ngx.log(ngx.INFO, "syncDictToTable fail,reqlimtrule")
		end
		local res = _M.insert_wafrules_table()
		if res ~= nil then
			ngx.log(ngx.INFO, string.format("syncDictToTableOk,key:%s",isSync))
		end
    end
end

--resty.limit.req
function _M.Reqlimit(limit_token,limit_method,rateV,limit_speed,uri)
    --local rate = math.ceil(rateV)
    local burst = math.ceil(rateV * 0.5)
    if rateV < 5 then
        burst = math.ceil(rateV)
    end
    --local rate = rateV
    --local burst = rate * 0.1
    local lim, err = limit_req.new("limitzone", rateV, burst)
    if not lim then
        ngx.log(ngx.WARN, "failed to instantiate a resty.limit.req object: ", err)
        --return ngx.exit(500)
        return true
    end

    local delay, err = lim:incoming(limit_token, true)
    if not delay then
        if err == "rejected" then
            _M.log_record('reqlimit',limit_token,limit_method, uri, "-", "-")
            if _M.GET('reqlimit_enable') == "record" then
                --true keep on,false break loop
                return false
            else       
                ngx.header.content_type = "text/html"
                --ngx.status = ngx.HTTP_SERVICE_UNAVAILABLE
                local limit_html = _M.GET("limit_html")
                local limit_code = _M.GET("reqlimit_statuscode")
                if limit_code == 401 then
                    local limiturl = string.format("/xf/verify.html?srcUrl=%s://%s%s",ngx.var.scheme,ngx.var.host,uri)
                    ngx.redirect(limiturl , 301)
                else
                    ngx.status = limit_code
                    ngx.say(limit_html)
                    ngx.exit(limit_code)
                    --return ngx.exit(503)
                end
            end
        end
        ngx.log(ngx.WARN, "failed to limit req: ", err)
        --return ngx.exit(500)
        return true
    end

    --limit request_time
    if limit_speed == "true" then
        if delay >= 0.001 then
            ngx.sleep(delay)
        end
    end

    return true
end

--resty.limit.count need count.lua enable resty.core and lua-nginx-module-0.10.24
function _M.LimitCount(limit_token,limit_method,rateV,expireT,limit_speed,uri)
    local lim, err = limit_count.new("limitzone", rateV, expireT)
    if not lim then
        ngx.log(ngx.WARN, "failed to instantiate a resty.limit.count object: ", err)
        --return ngx.exit(500)
        return true
    end

    local key = limit_token
    local delay, err = lim:incoming(key, true)
    if not delay then
        if err == "rejected" then
            _M.log_record('reqlimit',limit_token,limit_method, uri, "-", "-")
            if _M.GET('reqlimit_enable') == "record" then
                return true
            else       
                ngx.header.content_type = "text/html"
                local limit_html = _M.GET("limit_html")
                local limit_code = _M.GET("reqlimit_statuscode")
                ngx.status = limit_code
                ngx.say(limit_html)
                ngx.exit(limit_code)                     
                --return ngx.exit(503)
            end
        end
        ngx.log(ngx.WARN, "failed to limit count: ", err)
        --return ngx.exit(500)
        return true
    end
    return true
end


--reload config
function _M.ReloadConfig()
    local appname = _M.GET("appname")
    if appname == nil  then
        ngx.log(ngx.ERR, "ReadAppname Fail.")
        return nil
    end
    local resp = Xrequest(config.config_domain.."/api/config/v1/Version?appname="..appname)
	if resp ~= nil then
		local json = cjson.decode(resp)
		local cfgv = _M.GET("config_version")
		if tonumber(json.config_version) > tonumber(cfgv) then
            local wafruleresp = _M.load_waf_rule()	
            local blackipresp = _M.load_blackip_fromurl(cfgv)	
            local wafcfgresp = _M.load_waf_config()
            local riskipresp = _M.load_riskip_fromurl(cfgv)
            if wafruleresp ~= nil and blackipresp ~= nil and wafcfgresp ~= nil and riskipresp ~= nil then
                    ngx.log(ngx.INFO, string.format("WafConfigUpdateOk,new:%s,old:%s",json.config_version, cfgv))
                    _M.SET("config_version",json.config_version)
                    _M.SetExt("config_syncToTable","update",30)
                    return ok
            else
                    ngx.log(ngx.ERR, string.format("WafConfigUpdateFail,wafrule:%s,blackip:%s,wafcfg:%s",wafruleresp,blackipresp,wafcfgresp))
                    return nil
            end
		else
			ngx.log(ngx.DEBUG, string.format("WafConfigNoNeedUpdate,new:%s,old:%s",json.config_version, cfgv))
            return 'ok'
		end
	else
		ngx.log(ngx.ERR, "GetWafConfigVersion Fail.")	
        	return nil	
	end
end

--load waf config
function _M.load_waf_config()
        ngx.log(ngx.INFO, "load_waf_config")
        local appname = _M.GET("appname")
        if appname == nil  then
                ngx.log(ngx.ERR, "ReadAppname Fail.")
                return nil
        end
        local resp = Xrequest(config.config_domain.."/api/config/v1/GetConfig?appname="..appname)
        if resp ~= nil then
			local json = cjson.decode(resp)	
            if json ~= nil and json.id > 0 then
                --ngx.log(ngx.INFO, string.format("waf_enable:%s",config.waf_enable))
                _M.SET('waf_enable',json.waf_enable)
                --_M.SET('appname',json.appname)
                _M.SET('log_model',json.log_model)
                --_M.SET('log_dir',json.log_dir) --config from file
                _M.SET('kafka_broker_ip',json.kafka_broker_ip)
                _M.SET('waf_exclude_intranet',json.waf_exclude_intranet)
                _M.SET('waf_exclude_static',json.waf_exclude_static)
                --_M.SET('white_url_check',json.white_url_check)
                --_M.SET('white_ip_check',json.white_ip_check)
                --_M.SET('white_ua_check',json.white_ua_check)
                --_M.SET('white_rf_check',json.white_rf_check)                
                _M.SET('black_ip_check',json.black_ip_check)
                _M.SET('waf_urldeny_check',json.waf_urldeny_check)
                _M.SET('url_check',json.url_check)
                _M.SET('url_args_check',json.url_args_check)
                _M.SET('user_agent_check',json.user_agent_check)
                _M.SET('referer_check',json.referer_check)
                _M.SET('cookie_check',json.cookie_check)
                _M.SET('post_check',json.post_check)
                _M.SET('waf_model',json.waf_model)
                _M.SET('waf_url_length',json.waf_url_length)
                if json.waf_html ~= "" then
                    _M.SET('waf_html',json.waf_html)
                end
                _M.SET('waf_redirect_url',json.waf_redirect_url)
                _M.SET('waf_expire_time',json.waf_expire_time)
                _M.SET('risk_ip_check',json.risk_ip_check)
                _M.SET('waf_riskip_model',json.waf_riskip_model)
                _M.SET('waf_riskip_ratev',json.waf_riskip_ratev)
                
                _M.SET('reqlimit_enable',json.reqlimit_enable)
                _M.SET('reqlimit_exclude_intranet',json.reqlimit_exclude_intranet)
                _M.SET('reqlimit_exclude_static',json.reqlimit_exclude_static)
                _M.SET('region_deny_type',json.region_deny_type)
                if json.region ~= "" then
                    _M.SET('region',json.region)
                end
                _M.SET('reqlimit_exclude_subrequest',json.reqlimit_exclude_subrequest)
                _M.SET('reqlimit_exclude_internalrequest',json.reqlimit_exclude_internalrequest)                        
                _M.SET('white_list_enable',json.white_list_enable)
                _M.SET('reqlimit_statuscode',json.reqlimit_statuscode)
                if json.limit_html ~= "" then
                    _M.SET('limit_html',json.limit_html)
                end

                _M.SET('xwaf_config',resp)
                return "ok"
            else
                return nil
            end
        else
            return nil
	    end
end

--load wafrule
function _M.load_waf_rule()
        ngx.log(ngx.INFO, "load_waf_rule")
        local appname = _M.GET("appname")
        if appname == nil  then
                ngx.log(ngx.ERR, "ReadAppname Fail.")
                return nil
        end
        local resp = Xrequest(config.config_domain.."/api/rule/v1/GetList?appname="..appname)
	    if resp ~= nil then
            local ret = _M.SET('waf_rule',resp)
            ngx.log(ngx.INFO,string.format("load_waf_rule,result:%s",ret))
            return "ok"
        else
            return nil
	    end
end

--blackip
function _M.load_blackip_fromurl(cfgv)
        ngx.log(ngx.INFO, "load_blackip")
        local appname = _M.GET("appname")
        if appname == nil  then
                ngx.log(ngx.ERR, "ReadAppname Fail.")
                return nil
        end
        local resp = Xrequest(config.config_domain.."/api/blackip/v1/Iplist?appname="..appname.."&cfgv="..cfgv)
        if resp ~= nil then
            local json = cjson.decode(resp)
            if json.count > 0 then
                for _, item in pairs(json.data) do
                    --ngx.log(ngx.INFO, string.format("load_balckip:%s:%s", item.appname,item.ip))
                    _M.add_black_ip(item.ip,item.status,item.createtime,item.expiretime)
                end
            end
		    return "ok"
        else
            return nil
        end
end

--riskip
function _M.load_riskip_fromurl(cfgv)
    ngx.log(ngx.INFO, "load_riskip")
    local resp = Xrequest(config.config_domain.."/api/riskip/v1/Iplist?cfgv="..cfgv)
    if resp ~= nil then
        local json = cjson.decode(resp)
        if json.count > 0 then
            for _, item in pairs(json.data) do
                --ngx.log(ngx.INFO, string.format("load_riskip:%s", item.ip))
                _M.add_risk_ip(item.ip,item.is_malicious,item.risk_type)
            end
        end
        return "ok"
    else
        return nil
    end
end

-- load rule from one json file
function _M.insert_wafrules_table()
    ngx.log(ngx.INFO, "insert_wafrules_table.")
	local ruleTable = {
		args = {},
		blackip = {},
		cookie = {},
		post = {},
		url = {},
		useragent = {},
		referer = {},        
		--whiteip = {},
		--whiteua = {},      
		--whiterf = {},            
		--whiteurl = {}
	}
	local wafrules = _M.GET("waf_rule")
	local json = cjson.decode(wafrules)
	if wafrules ~= nil and json ~= nil and json.data ~= cjson.null then
		for _,rule in ipairs(json.data) do
            if rule.enable then
                ngx.log(ngx.DEBUG, string.format("%s:%s", rule.ruletype, rule.ruleitem))
                if rule.ruletype == "args" then
                        table.insert(ruleTable.args, rule.ruleitem)
                elseif rule.ruletype == "blackip" then
                        table.insert(ruleTable.blackip, rule.ruleitem)
                elseif rule.ruletype == "cookie" then
                        table.insert(ruleTable.cookie, rule.ruleitem)
                elseif rule.ruletype == "post" then
                        table.insert(ruleTable.post, rule.ruleitem)
                elseif rule.ruletype == "url" then
                        table.insert(ruleTable.url, rule.ruleitem)
                elseif rule.ruletype == "useragent" then
                        table.insert(ruleTable.useragent, rule.ruleitem)
                elseif rule.ruletype == "referer" then
                        table.insert(ruleTable.referer, rule.ruleitem)                        
                --elseif rule.ruletype == "whiteip" then
                --        table.insert(ruleTable.whiteip, rule.ruleitem)
                --elseif rule.ruletype == "whiteua" then
                --        table.insert(ruleTable.whiteua, rule.ruleitem)      
                --elseif rule.ruletype == "whiterf" then
                --        table.insert(ruleTable.whiterf, rule.ruleitem)                                           
                --elseif rule.ruletype == "whiteurl" then
                --        table.insert(ruleTable.whiteurl, rule.ruleitem)
                end
            end
		end
    	_M.RULE_TABLE = ruleTable
		return "ok"
	else
		ngx.log(ngx.INFO, string.format("insert_wafrules_table error,wafrule:%s",wafrules))	
		return nil
	end
end

-- load blackip in dict from file
function _M.load_blackip()
    ngx.log(ngx.INFO, "load_blackip_file")
	if config.blackip_list ~= nil then
	local json = cjson.decode(config.blackip_list)
   	for _, item in pairs(json.data) do
     		--ngx.log(ngx.DEBUG, string.format("load_balckip:%s:%s", item.appname,item.ip))
     		_M.add_black_ip(item.ip,item.status,item.createtime,item.expiretime)
       	end
	end
end

-- get all xff ip
function _M.get_client_ip()
    --local CLIENT_IP = ngx.req.get_headers()["X_real_ip"]
    --if CLIENT_IP == nil then
    --    CLIENT_IP = ngx.req.get_headers()["X_Forwarded_For"]
    --end
    local CLIENT_IP = ngx.req.get_headers()["X_Forwarded_For"]
    if CLIENT_IP == nil then
        CLIENT_IP  = ngx.var.remote_addr
    end
    if CLIENT_IP == nil then
        CLIENT_IP  = ""
    end
    local CLIENTIP,n = string.gsub(CLIENT_IP,"%s","") 
    return CLIENTIP
end

function _M.get_realip()
    local clientIp = _M.get_client_ip()
    local iparry = _M.split(clientIp,",")
    if #(iparry) > 0 then
        return iparry[1]
    else
        return ""
    end
end

-- use in black white ip 
function _M.get_all_ip()
    local ALL_IP = ""
    local XRIP = ngx.req.get_headers()["X_real_ip"]
    if XRIP then
	    ALL_IP = XRIP
    end 

    local  XFFIP = ngx.req.get_headers()["X_Forwarded_For"]
    if XFFIP ~= nil then
       if ALL_IP ~= "" then
	  ALL_IP = ALL_IP .. ',' .. XFFIP
       else
	  ALL_IP = XFFIP
       end
    end

    local RADDRIP  = ngx.var.remote_addr
    if RADDRIP ~= nil then
       if ALL_IP ~= "" then
          ALL_IP = ALL_IP .. ',' .. RADDRIP 
       else
          ALL_IP = RADDRIP 
       end
    end
    --ngx.log(ngx.DEBUG,ALL_IP)
    local ALLIP,n = string.gsub(ALL_IP,"%s","")
    return ALLIP
end

-- Get the segment C ip list
function _M.getcip_clientip()
    local CLIENT_IP = _M.get_client_ip()
    --local CLIENT_IP = _M.get_realip()
    --local CLIENT_IP = "192.168.11.26,192.168.103.23,192.168.100.32" 
    local CIP = ""
    if CLIENT_IP == nil then
         CIP = ""
    else
        local m = _M.split(CLIENT_IP,",")
    	for _, vv in pairs(m) do
    		local FTB = _M.split(vv,".")
    		if FTB ~= nil and #(FTB) == 4 then
        		CIP = CIP .. ',' .. FTB[1] .. '.' .. FTB[2] .. '.' .. FTB[3]
    		end
		end
    end
    --ngx.log(ngx.DEBUG, string.format("cip1:%s", CIP))

    local CIP,n = string.gsub(CIP,"^,","")
    --ngx.log(ngx.DEBUG, string.format("cip2:%s", CIP))
    return CIP
end

--get the segment c ip from a ip
function _M.getcip_realip()
    local realip = _M.get_realip()
    local FTB = _M.split(realip,".")
    local CIP = ""
    if FTB ~= nil and #(FTB) == 4 then
         CIP = FTB[1] .. '.' .. FTB[2] .. '.' .. FTB[3]
    end
    return CIP
end

function _M.getcip_ip(ip)
    local FTB = _M.split(ip,".")
    local CIP = ""
    if FTB ~= nil and #(FTB) == 4 then
         CIP = FTB[1] .. '.' .. FTB[2] .. '.' .. FTB[3]
    end
    return CIP
end

-- Get useragent
function _M.get_user_agent()
    local USER_AGENT = ngx.var.http_user_agent
    -- ngx.log(ngx.DEBUG, string.format("ua:%s", USER_AGENT))
    if USER_AGENT == nil then
        USER_AGENT = ""
    end
    return USER_AGENT
end

-- Get upstream_addr
--function _M.get_upstream_addr()
--    local UPA = ngx.var.upstream_addr
--    if UPA == nil then
--        UPA = "no"
--    end
--    return UPA
--end

-- Get referer
function _M.get_referer()
    local REFERER = ngx.var.http_referer
    if REFERER == nil then
        REFERER = ""
    end
    return REFERER
end

-- Get the host
function _M.get_host()
    local HOST = ngx.var.host
    if HOST == nil then
        HOST = ""
    end
    return HOST
end

function _M.split(str,pattern)
    local ret= {}
    string.gsub(str, "[^".. pattern .."]+", function(item) table.insert(ret, item) end )
    return  ret;
end


--http reqeust return json
--need nginx resolver 192.168.1.1;
function Xrequest(url)
    local httpc = zhttp.new()
    local timeout = timeout or 5000
    httpc:set_timeout(timeout)
    local res, err = httpc:request_uri(url, {
            ssl_verify = ssl_verify or false,
            method = "GET",
            headers = {
                ["Content-Type"] = "application/json",
                ["Auth-Token"] = config.api_token,
            }
    })
    httpc:set_keepalive(5000, 100)
    httpc:close()
    if not res then
    	ngx.log(ngx.ERR,string.format("xrequest %s Fail:%s",url,err))
        return nil
    end

    if res.status ~= 200 then
    	ngx.log(ngx.ERR,string.format("xrequest %s Fail:%d",url,res.status))
        return nil
    end
    --ngx.log(ngx.INFO,res.body)
    return res.body
end

--post log 
local function http_post_client(url, method, timeout,body)
        local httpc = zhttp.new() 
        timeout = timeout or 3000
        httpc:set_timeout(timeout)
        local res, err_ = httpc:request_uri(url, {
                method = "POST",
				body = body,
                headers = {
                    ["Content-Type"] = "application/json",
                }
        })
        httpc:set_keepalive(5000, 100)
        httpc:close()
		if not res then	
			return nil,err_
		elseif res.status == 200 then
			return res.body,err_
		else
			return nil,err_
		end
end

-- log record
function _M.log_record(log_type,block_info, method, url, data, ruletag)
    local log_path = config.log_dir
    local client_IP = _M.get_realip()
    local user_agent = _M.get_user_agent()
    local server_name = ngx.var.host
    local server_ip = ngx.var.server_addr
    --local server_ip = _M.get_realip()
    local local_time = string.gsub(ngx.localtime(),"%s","T")
    local appname = config.appname
    local log_json_obj = {
        appName = appname,
        blockInfo = block_info,
        logType = log_type,
        clientIp= client_IP,
        hTime = local_time,
        serverName = server_name,
        serverIp = server_ip,
        userAgent = user_agent,
        attackType = method,
        reqUrl = url,
        reqData = data,
        ruleTag = ruletag,
    }

	--local log_line = cjson.encode(log_json_obj)
	--if config.log_model == "http" then
	--	local resp, err = http_post_client("http://192.168.1.1/waflog",log_line,3000)
	--	ngx.log(ngx.DEBUG, string.format("httppost send:%s,err:%s", resp,err))
	--elseif
    local logmodel = _M.GET("log_model")
    if logmodel == "kafka" then
        local log_line = cjson.encode(log_json_obj)
        local kfk_ip = _M.GET("kafka_broker_ip")
        if kfk_ip == nil  then
            --ngx.log(ngx.ERR, "Read kafka_broker_ip Fail.")
            kfk_ip = config.kafka_broker_ip
        end
		local broker_list = {  
			{ host = kfk_ip, port = 9092 },
		}
		local bp = producer:new(broker_list, { producer_type = "async" }) 
		local ok, err = bp:send("xwaf_log", nil, log_line)  
		if not ok then  
			ngx.log(ngx.ERR, "kafka send err:", err)  
			return  
		end 
    elseif logmodel == "errorlog" then
        local log_line = string.format("logType:%s,attackType:%s,realIp:%s,blockInfo:%s,ruleTag:%s",log_type,method,client_IP,block_info,ruletag)
        ngx.log(ngx.ERR, log_line)
	else
		if log_path == nil then
			log_path = "/tmp"
		end
        local log_line = cjson.encode(log_json_obj)
		local log_name = string.format("%s/xwaf_%s.log", log_path, ngx.today())
		local file = io.open(log_name, "a")
		if file == nil then
			return
		end

		file:write(string.format("%s\n", log_line))
		file:flush()
		file:close()		
	end
end

-- block response
function _M.waf_output()
    local wafmodel = _M.GET("waf_model")
    if wafmodel == "redirect" then
        local wafurl = _M.GET("waf_redirect_url")
        if wafurl ~= nil then
            ngx.redirect(wafurl , 301)
        else
            ngx.header.content_type = "text/html"
            local wafhtml = _M.GET("waf_html")
            ngx.status = ngx.HTTP_FORBIDDEN
            ngx.say(wafhtml)
            ngx.exit(403)
        end
    elseif wafmodel == "deny" then
        -- ngx.log(ngx.DEBUG,string.format("set badip:%s", bad_ip))
        local bad_ip = _M.get_client_ip()
        local wet = _M.GET("waf_expire_time")
        _M.set_bad_ip(bad_ip, wet)
    else
        ngx.header.content_type = "text/html"
        --ngx.status = 405
        local wafhtml = _M.GET("waf_html")
        ngx.status = ngx.HTTP_FORBIDDEN
        --ngx.say(string.format(config.output_html, _M.get_client_ip()))
        ngx.say(wafhtml)
        ngx.exit(403)
    end
end

function _M.waf_risk_output(risk_type)
    local waf_riskip_model = _M.GET("waf_riskip_model")
    if waf_riskip_model == "reqlimit" and risk_type == "limit" then
        local ratev = _M.GET("waf_riskip_ratev")
        _M.Reqlimit("AllRiskIp","RISK_IP_LIMIT",ratev,false,ngx.var.uri)	
    else
        ngx.header.content_type = "text/html"
        local wafhtml = _M.GET("waf_html")
        ngx.status = ngx.HTTP_FORBIDDEN
        ngx.say(wafhtml)
        ngx.exit(403)
    end
end

-- set bad ip
function _M.set_bad_ip(bad_ip, expire_time)
    local limitbadip = ngx.shared.blackip
    local req,_ = limitbadip:get("bad"..bad_ip)
    if req == nil then
        limitbadip:set("bad"..bad_ip, 3, expire_time)
    end
end

function _M.add_black_ip(ip,status,createtime,expiretime)
    local blackip = ngx.shared.blackip
    if status == 1 then
        if expiretime > 0 then
            local nowT = os.time()
            local expireT = createtime + expiretime - nowT
            if expireT > 0 then
                ngx.log(ngx.DEBUG,string.format("add_blackip:%s,%s,%d", ip,status,expireT))
                blackip:set(ip, 1, expireT)                
            end
            --lt 0 is createtime too long
            --success, err, forcible = blackip:set(ip, 1, expire_time)
            --ngx.log(ngx.DEBUG,string.format("add_blackip result:%s,%s,%d", success,err,forcible))
        else
            --ngx.log(ngx.DEBUG,string.format("add_blackip:%s,%s,0", ip,status))
            blackip:set(ip, 1)
        end
    else
        blackip:delete(ip)
    end
end

function _M.add_risk_ip(ip,status,risk_type)
    local riskip = ngx.shared.blackip
    if risk_type ~= "trust" and risk_type ~= "" then
            --ngx.log(ngx.DEBUG,string.format("add_riskip:%s,%s", ip,status))
            riskip:set("risk"..ip, risk_type)
    else
        riskip:delete("risk"..ip)
    end
end

return _M
